<template>
  <div class="insert-menu-wrapper">
    <!-- + 号按钮 -->
    <transition name="fade">
      <button
        v-if="showInsertButton"
        class="insert-button"
        :style="insertButtonStyle"
        title="插入内容"
        @click="toggleInsertMenu"
        @mousedown.prevent
        @mouseenter="onButtonMouseEnter"
        @mouseleave="onButtonMouseLeave"
      >
        <div class="insert-icon">+</div>
      </button>
    </transition>

    <!-- 插入菜单 -->
    <transition name="slide-fade">
      <div
        v-if="showInsertMenu"
        class="insert-menu"
        :style="insertMenuStyle"
        @mousedown.prevent
      >
        <!-- 搜索提示 -->
        <div v-if="searchKeyword" class="search-hint">
          <span>搜索: "{{ searchKeyword }}" ({{ filteredItems.length }} 个结果)</span>
        </div>

        <!-- 动态渲染过滤后的菜单项 -->
        <div class="menu-section">
          <div class="section-title">{{ searchKeyword ? '搜索结果' : '所有组件' }}</div>
          <div class="filtered-grid">
            <div
              v-for="(item, index) in filteredItems"
              :key="item.type"
              class="menu-item-card"
              :class="{
                'selected-item': index === 0 && !searchKeyword,
                'keyboard-selected': index === selectedItemIndex
              }"
              :title="item.label"
              @click="item.action"
            >
              <!-- 基本组件图标 -->
              <div v-if="item.category === 'basic'" class="item-icon basic-icon">
                <template v-if="item.type === 'paragraph'">¶</template>
                <template v-else-if="item.type === 'heading2'">H2</template>
                <template v-else-if="item.type === 'heading3'">H3</template>
                <template v-else-if="item.type === 'heading4'">H4</template>
                <template v-else-if="item.type === 'heading5'">H5</template>
                <template v-else-if="item.type === 'heading6'">H6</template>
                <template v-else-if="item.type === 'bulletList'">•</template>
                <template v-else-if="item.type === 'orderedList'">1.</template>
                <template v-else-if="item.type === 'blockquote'">"</template>
                <template v-else-if="item.type === 'codeBlock'">&lt;/&gt;</template>
                <template v-else-if="item.type === 'horizontalRule'">──</template>
              </div>

              <!-- 组件类图标 -->
              <div v-else class="item-icon component-icon">
                <template v-if="item.type === 'table'">⊞</template>
                <template v-else-if="item.type === 'image'">🖼️</template>
                <template v-else-if="item.type === 'video'">📹</template>
                <template v-else>⚡</template>
              </div>

              <!-- 组件标签和关键词匹配高亮 -->
              <div class="item-label" v-html="highlightKeyword(item.label)" />
            </div>
          </div>

          <!-- 无搜索结果提示 -->
          <div v-if="searchKeyword && filteredItems.length === 0" class="no-results">
            <div class="no-results-text">未找到匹配的组件</div>
            <div class="no-results-hint">尝试搜索: table, image, heading, list 等</div>
          </div>
        </div>
      </div>
    </transition>

    <!-- 图片插入对话框 -->
    <el-dialog
      title="插入图片"
      :visible.sync="imageDialogVisible"
      append-to-body
      width="500px"
      @close="resetImageDialog"
    >
      <el-form :model="imageForm" label-width="80px">
        <el-form-item label="图片URL">
          <el-input
            v-model="imageForm.url"
            placeholder="输入图片链接"
            @keyup.enter.native="insertImage"
          />
        </el-form-item>
        <el-form-item label="替代文本">
          <el-input
            v-model="imageForm.alt"
            placeholder="图片描述文本"
          />
        </el-form-item>
        <el-form-item label="标题">
          <el-input
            v-model="imageForm.title"
            placeholder="图片标题（可选）"
          />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="imageDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="insertImage">插入</el-button>
      </div>
    </el-dialog>

    <!-- 视频插入对话框 -->
    <el-dialog
      title="插入视频"
      :visible.sync="videoDialogVisible"
      width="500px"
      append-to-body
      @close="resetVideoDialog"
    >
      <el-form :model="videoForm" label-width="100px">
        <el-form-item label="YouTube URL">
          <el-input
            v-model="videoForm.url"
            placeholder="输入YouTube视频链接"
            @keyup.enter.native="insertVideo"
          />
        </el-form-item>
        <el-form-item label="视频宽度">
          <el-input
            v-model="videoForm.width"
            placeholder="560"
          />
        </el-form-item>
        <el-form-item label="视频高度">
          <el-input
            v-model="videoForm.height"
            placeholder="315"
          />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button @click="videoDialogVisible = false">取消</el-button>
        <el-button type="primary" @click="insertVideo">插入</el-button>
      </div>
    </el-dialog>

    <!-- 短代码插入对话框 -->
    <el-dialog
      title="插入短代码"
      append-to-body
      :visible.sync="shortcodeDialogVisible"
      width="600px"
      @close="resetShortcodeDialog"
    >
      <div class="shortcode-list">
        <div
          v-for="shortcode in shortcodes"
          :key="shortcode.name"
          class="shortcode-item"
          @click="selectShortcode(shortcode)"
        >
          <div class="shortcode-icon">{{ shortcode.icon }}</div>
          <div class="shortcode-info">
            <div class="shortcode-name">{{ shortcode.label }}</div>
            <div class="shortcode-desc">{{ shortcode.description }}</div>
          </div>
        </div>
      </div>
      <div v-if="selectedShortcode" class="shortcode-config">
        <h4>配置参数</h4>
        <el-form :model="shortcodeParams" label-width="100px">
          <el-form-item
            v-for="param in selectedShortcode.params"
            :key="param.name"
            :label="param.label"
          >
            <el-input
              v-if="param.type === 'text'"
              v-model="shortcodeParams[param.name]"
              :placeholder="param.placeholder"
            />
            <el-select
              v-else-if="param.type === 'select'"
              v-model="shortcodeParams[param.name]"
              :placeholder="param.placeholder"
            >
              <el-option
                v-for="option in param.options"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
            <el-switch
              v-else-if="param.type === 'boolean'"
              v-model="shortcodeParams[param.name]"
            />
          </el-form-item>
        </el-form>
        <div class="shortcode-preview">
          <strong>预览代码：</strong>
          <code>{{ generateShortcodeString() }}</code>
        </div>
      </div>
      <div slot="footer">
        <el-button @click="shortcodeDialogVisible = false">取消</el-button>
        <el-button type="primary" :disabled="!selectedShortcode" @click="insertShortcode">插入</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import shortcodeConfig from './shortcode-config.js'

export default {
  name: 'InsertMenu',
  props: {
    editor: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      showInsertButton: false,
      showInsertMenu: false,
      buttonHovered: false,
      insertButtonStyle: {
        top: '0px',
        left: '0px'
      },
      insertMenuStyle: {
        top: '0px',
        left: '0px'
      },
      currentPosition: null,

      // 图片对话框
      imageDialogVisible: false,
      imageForm: {
        url: '',
        alt: '',
        title: ''
      },

      // 视频对话框
      videoDialogVisible: false,
      videoForm: {
        url: '',
        width: '560',
        height: '315'
      },

      // 短代码对话框
      shortcodeDialogVisible: false,
      shortcodes: shortcodeConfig,
      selectedShortcode: null,
      shortcodeParams: {},

      // 键盘导航
      selectedItemIndex: 0, // 默认选中第一个（段落）
      menuItems: [],

      // 搜索过滤
      searchKeyword: '',
      filteredItems: []
    }
  },

  watch: {
    editor: {
      handler(newEditor) {
        if (newEditor) {
          this.initEditor()
        }
      },
      immediate: true
    }
  },
  mounted() {
    this.initEditor()
  },
  beforeDestroy() {
    if (this.editor) {
      this.editor.off('selectionUpdate', this.handleSelectionUpdate)
      this.editor.off('update', this.handleSelectionUpdate)
      this.editor.off('focus', this.handleSelectionUpdate)
      this.editor.off('blur', this.handleBlur)
    }
    // 移除全局点击监听器
    document.removeEventListener('click', this.handleGlobalClick)
    // 键盘事件由主编辑器统一处理，这里不需要移除
  },
  methods: {
    initEditor() {
      if (this.editor && this.editor.view) {
        // 移除旧的事件监听器
        this.editor.off('selectionUpdate', this.handleSelectionUpdate)
        this.editor.off('update', this.handleSelectionUpdate)
        this.editor.off('focus', this.handleSelectionUpdate)
        this.editor.off('blur', this.handleBlur)

        // 移除旧的全局点击监听器
        document.removeEventListener('click', this.handleGlobalClick)

        // 添加新的事件监听器
        this.editor.on('selectionUpdate', this.handleSelectionUpdate)
        this.editor.on('update', this.handleSelectionUpdate)
        this.editor.on('focus', this.handleSelectionUpdate)
        this.editor.on('blur', this.handleBlur)

        // 添加全局点击监听器
        document.addEventListener('click', this.handleGlobalClick)

        // 键盘事件由主编辑器统一处理，不在这里重复添加监听器

        // 初始检查
        this.$nextTick(() => {
          this.checkEmptyLine()
        })
      }
    },

    handleSelectionUpdate() {
      this.$nextTick(() => {
        this.checkEmptyLine()
      })
    },

    handleBlur() {
      // 编辑器失去焦点时不自动隐藏按钮，让用户主动控制
      // setTimeout(() => {
      //   if (!this.showInsertMenu && this.editor && !this.editor.view.hasFocus()) {
      //     this.showInsertButton = false
      //   }
      // }, 500)
    },

    checkEmptyLine() {
      if (!this.editor || !this.editor.view) {
        return
      }

      try {
        const { state, view } = this.editor
        const { selection } = state

        // 检查当前光标是否在空段落中
        const $pos = selection.$anchor
        const node = $pos.parent

        // 更全面的空行检测
        const isEmpty = node.type.name === 'paragraph' &&
                       node.content.size === 0 &&
                       selection.empty

        const hasFocus = view.hasFocus()

        // 检查是否在表格中
        const isInTable = this.editor.isActive('table')

        // 检查是否在斜杠命令模式
        const textContent = node.textContent || ''
        const hasSlashCommand = textContent.includes('/') && node.type.name === 'paragraph'

        // console.log('InsertMenu debug:', {
        //   nodeType: node.type.name,
        //   contentSize: node.content.size,
        //   selectionEmpty: selection.empty,
        //   hasFocus: hasFocus,
        //   isEmpty: isEmpty,
        //   isInTable: isInTable,
        //   hasSlashCommand: hasSlashCommand,
        //   textContent: textContent,
        //   shouldShow: (isEmpty || hasSlashCommand) && hasFocus && !isInTable
        // })

        // 在表格中时不显示插入按钮，因为浮动工具栏会处理表格操作
        // 修改显示条件：空行或斜杠命令模式都显示
        if ((isEmpty || hasSlashCommand) && hasFocus && !isInTable) {
          this.showInsertButton = true
          this.calculateButtonPosition()
        } else if ((!isEmpty && !hasSlashCommand) || isInTable) {
          // 如果不在空行且不在斜杠命令模式，或者在表格中，隐藏按钮
          this.showInsertButton = false
          this.showInsertMenu = false

          // 更新编辑器 storage
          if (this.editor && this.editor.storage) {
            this.editor.storage.insertMenuVisible = false
            this.editor.storage.insertMenuComponent = null
          }
        }
        // 如果编辑器失去焦点但仍在空行，保持按钮显示
      } catch (error) {
        console.warn('InsertMenu checkEmptyLine error:', error)
        this.showInsertButton = false
        this.showInsertMenu = false
      }
    },

    calculateButtonPosition() {
      if (!this.editor || !this.editor.view) return

      try {
        const { view } = this.editor
        const { selection } = this.editor.state

        // 获取编辑器容器
        const editorElement = document.querySelector('.ai-tiptap-editor')
        if (!editorElement) return

        const contentContainer = editorElement.querySelector('.tiptap-content')
        if (!contentContainer) return

        // 获取光标位置
        const coords = view.coordsAtPos(selection.from)

        // 获取容器相对于视口的位置
        const containerRect = contentContainer.getBoundingClientRect()

        // 计算按钮位置
        // X坐标：在ProseMirror内容区域的左边缘（考虑到20px的padding）
        const x = -5 // 刚好在左边缘

        // Y坐标：与当前行对齐
        const y = coords.top - containerRect.top + 2

        // console.log('Button position calculation:', {
        //   coords: coords,
        //   containerRect: containerRect,
        //   calculatedX: x,
        //   calculatedY: y
        // })

        this.insertButtonStyle = {
          top: y + 'px',
          left: x + 'px'
        }

        this.currentPosition = selection.from
      } catch (error) {
        console.warn('InsertMenu calculateButtonPosition error:', error)
      }
    },

    onButtonMouseEnter() {
      // 鼠标进入按钮时保持显示
      this.buttonHovered = true
    },

    onButtonMouseLeave() {
      // 鼠标离开按钮时不自动隐藏，让用户主动控制
      this.buttonHovered = false
      // setTimeout(() => {
      //   if (!this.buttonHovered && !this.showInsertMenu && this.editor && !this.editor.view.hasFocus()) {
      //     this.showInsertButton = false
      //   }
      // }, 300)
    },

    toggleInsertMenu() {
      this.showInsertMenu = !this.showInsertMenu

      // 更新编辑器 storage
      if (this.editor && this.editor.storage) {
        this.editor.storage.insertMenuVisible = this.showInsertMenu
        this.editor.storage.insertMenuComponent = this.showInsertMenu ? this : null
      }

      if (this.showInsertMenu) {
        this.calculateMenuPosition()
        this.initMenuItems() // 初始化菜单项
        this.$nextTick(() => {
          this.updateVisualSelection()
        })
      }
    },

    // 外部触发显示菜单的方法
    forceShowMenu() {
      this.showInsertButton = true
      this.calculateButtonPosition()

      // 重置搜索关键词
      this.searchKeyword = ''
      this.initMenuItems() // 初始化菜单项

      this.$nextTick(() => {
        this.showInsertMenu = true

        // 更新编辑器 storage
        if (this.editor && this.editor.storage) {
          this.editor.storage.insertMenuVisible = true
          this.editor.storage.insertMenuComponent = this
        }

        this.calculateMenuPositionForSlash()
        // 延迟一点设置视觉选中状态，确保DOM已渲染
        this.$nextTick(() => {
          this.updateVisualSelection()
          // 立即检查是否有关键词需要过滤
          this.checkAndUpdateKeyword()
        })
      })
    },

    // 检查并更新关键词
    checkAndUpdateKeyword() {
      if (!this.editor) return

      try {
        const { state } = this.editor
        const { selection } = state
        const node = selection.$anchor.parent
        const textContent = node.textContent || ''
        const lastSlashIndex = textContent.lastIndexOf('/')

        if (lastSlashIndex !== -1) {
          const cursorPos = selection.from - selection.$anchor.start()
          if (cursorPos > lastSlashIndex) {
            const keyword = textContent.substring(lastSlashIndex + 1, cursorPos)
            if (keyword !== this.searchKeyword) {
              this.searchKeyword = keyword
              this.filterItems()
            }
          }
        }
      } catch (error) {
        console.warn('checkAndUpdateKeyword error:', error)
      }
    },

    // 专门为斜杠命令优化的菜单位置计算
    calculateMenuPositionForSlash() {
      try {
        // 获取编辑器工具栏位置
        const editorElement = document.querySelector('.ai-tiptap-editor')
        if (!editorElement) return

        const toolbar = editorElement.querySelector('.ai-toolbar')
        if (!toolbar) return

        const toolbarRect = toolbar.getBoundingClientRect()

        // 使用viewport坐标(position: fixed)
        // 菜单显示在工具栏正下方,水平居中
        const top = toolbarRect.bottom + 8 // 工具栏下方8px

        this.insertMenuStyle = {
          top: top + 'px'
          // left使用CSS中的50% + transform居中
        }
      } catch (error) {
        console.warn('calculateMenuPositionForSlash error:', error)
        this.insertMenuStyle = {}
      }
    },

    hideInsertMenu() {
      this.showInsertMenu = false

      // 更新编辑器 storage
      if (this.editor && this.editor.storage) {
        this.editor.storage.insertMenuVisible = false
        this.editor.storage.insertMenuComponent = null
      }
    },

    // 清除斜杠命令字符
    clearSlashCommand() {
      if (!this.editor) return

      try {
        const { state } = this.editor
        const { selection } = state
        const node = selection.$anchor.parent
        const textContent = node.textContent || ''

        // 查找最后一个斜杠的位置
        const lastSlashIndex = textContent.lastIndexOf('/')

        if (lastSlashIndex !== -1) {
          // 计算斜杠在文档中的绝对位置
          const nodeStart = selection.$anchor.start()
          const slashPosition = nodeStart + lastSlashIndex
          const currentPosition = selection.from

          // 删除从斜杠到当前光标位置的所有文本
          this.editor.chain().focus().deleteRange({
            from: slashPosition,
            to: currentPosition
          }).run()
        }

        // 重置搜索关键词
        this.searchKeyword = ''
      } catch (error) {
        console.warn('clearSlashCommand error:', error)
      }
    },

    // 键盘导航方法
    initMenuItems() {
      // 定义所有可选的菜单项，包含关键词
      this.menuItems = [
        {
          type: 'paragraph',
          label: '段落',
          keywords: ['paragraph', 'p', '段落', 'text', '文本'],
          category: 'basic',
          action: () => this.insertParagraph()
        },
        {
          type: 'heading2',
          label: '标题 2',
          keywords: ['heading', 'h2', '标题', 'title', 'header', '二级标题'],
          category: 'basic',
          action: () => this.insertHeading(2)
        },
        {
          type: 'heading3',
          label: '标题 3',
          keywords: ['heading', 'h3', '标题', 'title', 'header', '三级标题'],
          category: 'basic',
          action: () => this.insertHeading(3)
        },
        {
          type: 'heading4',
          label: '标题 4',
          keywords: ['heading', 'h4', '标题', 'title', 'header', '四级标题'],
          category: 'basic',
          action: () => this.insertHeading(4)
        },
        {
          type: 'heading5',
          label: '标题 5',
          keywords: ['heading', 'h5', '标题', 'title', 'header', '五级标题'],
          category: 'basic',
          action: () => this.insertHeading(5)
        },
        {
          type: 'heading6',
          label: '标题 6',
          keywords: ['heading', 'h6', '标题', 'title', 'header', '六级标题'],
          category: 'basic',
          action: () => this.insertHeading(6)
        },
        {
          type: 'bulletList',
          label: '无序列表',
          keywords: ['bullet', 'list', 'ul', '列表', '无序', 'unordered', '点列表'],
          category: 'basic',
          action: () => this.insertBulletList()
        },
        {
          type: 'orderedList',
          label: '有序列表',
          keywords: ['ordered', 'list', 'ol', '列表', '有序', 'number', '数字列表'],
          category: 'basic',
          action: () => this.insertOrderedList()
        },
        {
          type: 'blockquote',
          label: '引用块',
          keywords: ['quote', 'blockquote', '引用', 'citation', '引述'],
          category: 'basic',
          action: () => this.insertBlockquote()
        },
        {
          type: 'codeBlock',
          label: '代码块',
          keywords: ['code', 'pre', '代码', 'programming', '程序', 'script'],
          category: 'basic',
          action: () => this.insertCodeBlock()
        },
        {
          type: 'horizontalRule',
          label: '分割线',
          keywords: ['hr', 'line', 'divider', '分割', '分隔', 'separator', '横线'],
          category: 'basic',
          action: () => this.insertHorizontalRule()
        },
        {
          type: 'table',
          label: '表格',
          keywords: ['table', 'grid', '表格', '表', 'spreadsheet', 'data'],
          category: 'component',
          action: () => this.insertTable()
        },
        {
          type: 'image',
          label: '图片',
          keywords: ['image', 'img', 'picture', '图片', '图像', 'photo'],
          category: 'media',
          action: () => this.showImageDialog()
        },
        {
          type: 'video',
          label: '视频',
          keywords: ['video', 'youtube', '视频', 'media', '媒体'],
          category: 'media',
          action: () => this.showVideoDialog()
        }
      ]
      this.filterItems() // 初始化过滤结果
    },

    // 过滤菜单项
    filterItems() {
      if (!this.searchKeyword) {
        this.filteredItems = [...this.menuItems]
      } else {
        const keyword = this.searchKeyword.toLowerCase()
        this.filteredItems = this.menuItems.filter(item => {
          // 检查标签名称
          if (item.label.toLowerCase().includes(keyword)) {
            return true
          }
          // 检查关键词列表
          return item.keywords.some(kw => kw.toLowerCase().includes(keyword))
        })
      }

      // 重置选中索引，确保不越界
      this.selectedItemIndex = 0
      this.$nextTick(() => {
        this.updateVisualSelection()
      })
    },

    selectCurrentItem() {
      if (this.filteredItems[this.selectedItemIndex]) {
        this.filteredItems[this.selectedItemIndex].action()
      }
    },

    navigateUp() {
      if (this.selectedItemIndex > 0) {
        this.selectedItemIndex--
        this.updateVisualSelection()
      }
    },

    navigateDown() {
      if (this.selectedItemIndex < this.filteredItems.length - 1) {
        this.selectedItemIndex++
        this.updateVisualSelection()
      }
    },

    updateVisualSelection() {
      // 移除所有选中状态
      const items = this.$el.querySelectorAll('.menu-item-card')
      items.forEach(item => item.classList.remove('keyboard-selected'))

      // 添加当前选中项的高亮
      if (items[this.selectedItemIndex]) {
        items[this.selectedItemIndex].classList.add('keyboard-selected')
      }
    },

    // 高亮搜索关键词
    highlightKeyword(text) {
      if (!this.searchKeyword) return text

      const keyword = this.searchKeyword.toLowerCase()
      const regex = new RegExp(`(${keyword})`, 'gi')
      return text.replace(regex, '<mark>$1</mark>')
    },

    handleKeyNavigation(event) {
      // 只有在菜单显示时才处理键盘导航
      if (!this.showInsertMenu) return false

      // 检查事件是否来自编辑器区域
      const editorElement = document.querySelector('.ai-tiptap-editor')
      if (!editorElement || !editorElement.contains(event.target)) {
        return false
      }

      switch (event.key) {
        case 'Enter':
          event.preventDefault()
          event.stopPropagation()
          this.selectCurrentItem()
          return true
        case 'Escape':
          event.preventDefault()
          event.stopPropagation()
          this.hideInsertMenu()
          return true
        case 'ArrowUp':
          event.preventDefault()
          event.stopPropagation()
          this.navigateUp()
          return true
        case 'ArrowDown':
          event.preventDefault()
          event.stopPropagation()
          this.navigateDown()
          return true
        default:
          return false
      }
    },

    handleGlobalClick(event) {
      // 如果菜单是打开的，检查点击是否在菜单或按钮外部
      if (this.showInsertMenu) {
        const insertMenu = this.$el.querySelector('.insert-menu')
        const insertButton = this.$el.querySelector('.insert-button')

        // 检查点击是否在菜单、按钮或对话框内部
        const isInsideMenu = insertMenu && insertMenu.contains(event.target)
        const isInsideButton = insertButton && insertButton.contains(event.target)
        const isInsideDialog = event.target.closest('.el-dialog')

        // 如果点击在外部，关闭菜单
        if (!isInsideMenu && !isInsideButton && !isInsideDialog) {
          this.showInsertMenu = false
        }
      }
    },

    calculateMenuPosition() {
      try {
        // 获取编辑器工具栏位置
        const editorElement = this.$el.closest('.ai-tiptap-editor')
        if (!editorElement) return

        const toolbar = editorElement.querySelector('.ai-toolbar')
        if (!toolbar) return

        const toolbarRect = toolbar.getBoundingClientRect()

        // 使用viewport坐标(position: fixed)
        // 菜单显示在工具栏正下方,水平居中
        const top = toolbarRect.bottom + 8 // 工具栏下方8px

        this.insertMenuStyle = {
          top: top + 'px'
          // left使用CSS中的50% + transform居中
        }
      } catch (error) {
        console.warn('calculateMenuPosition error:', error)
        this.insertMenuStyle = {}
      }
    },

    // 基本富文本插入方法
    insertParagraph() {
      // 清除可能存在的斜杠字符
      this.clearSlashCommand()
      // 确保当前元素是段落格式
      this.editor.chain().focus().setParagraph().run()
      this.hideInsertMenu()
    },

    insertHeading(level) {
      // 清除可能存在的斜杠字符
      this.clearSlashCommand()
      this.editor.chain().focus().setHeading({ level }).run()
      this.hideInsertMenu()
    },

    insertBulletList() {
      this.clearSlashCommand()
      this.editor.chain().focus().toggleBulletList().run()
      this.hideInsertMenu()
    },

    insertOrderedList() {
      this.clearSlashCommand()
      this.editor.chain().focus().toggleOrderedList().run()
      this.hideInsertMenu()
    },

    insertBlockquote() {
      this.clearSlashCommand()
      this.editor.chain().focus().toggleBlockquote().run()
      this.hideInsertMenu()
    },

    insertCodeBlock() {
      this.clearSlashCommand()
      this.editor.chain().focus().toggleCodeBlock().run()
      this.hideInsertMenu()
    },

    insertHorizontalRule() {
      this.clearSlashCommand()
      this.editor.chain().focus().setHorizontalRule().run()
      this.hideInsertMenu()
    },

    insertTable() {
      this.clearSlashCommand()
      this.editor.chain().focus().insertTable({
        rows: 3,
        cols: 3,
        withHeaderRow: true
      }).run()
      this.hideInsertMenu()
    },

    // 媒体插入方法
    showImageDialog() {
      this.hideInsertMenu()
      this.imageDialogVisible = true
    },

    resetImageDialog() {
      this.imageForm = {
        url: '',
        alt: '',
        title: ''
      }
    },

    insertImage() {
      if (!this.imageForm.url) {
        this.$message.warning('请输入图片链接')
        return
      }

      const attrs = {
        src: this.imageForm.url,
        alt: this.imageForm.alt || ''
      }

      if (this.imageForm.title) {
        attrs.title = this.imageForm.title
      }

      this.editor.chain().focus().setImage(attrs).run()
      this.imageDialogVisible = false
      this.resetImageDialog()
    },

    showVideoDialog() {
      this.hideInsertMenu()
      this.videoDialogVisible = true
    },

    resetVideoDialog() {
      this.videoForm = {
        url: '',
        width: '560',
        height: '315'
      }
    },

    insertVideo() {
      if (!this.videoForm.url) {
        this.$message.warning('请输入YouTube视频链接')
        return
      }

      const videoId = this.extractYouTubeId(this.videoForm.url)
      if (!videoId) {
        this.$message.error('无效的YouTube链接')
        return
      }

      const embedUrl = `https://www.youtube.com/embed/${videoId}`

      this.editor.chain().focus().setVideo({
        src: embedUrl,
        width: parseInt(this.videoForm.width) || 560,
        height: parseInt(this.videoForm.height) || 315
      }).run()

      this.videoDialogVisible = false
      this.resetVideoDialog()
    },

    extractYouTubeId(url) {
      const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/
      const match = url.match(regExp)
      return (match && match[2].length === 11) ? match[2] : null
    },

    // 短代码方法
    showShortcodeDialog() {
      this.hideInsertMenu()
      this.shortcodeDialogVisible = true
    },

    resetShortcodeDialog() {
      this.selectedShortcode = null
      this.shortcodeParams = {}
    },

    selectShortcode(shortcode) {
      this.selectedShortcode = shortcode
      this.shortcodeParams = {}

      // 初始化参数默认值
      shortcode.params.forEach(param => {
        this.shortcodeParams[param.name] = param.default || ''
      })
    },

    generateShortcodeString() {
      if (!this.selectedShortcode) return ''

      let shortcodeStr = `[${this.selectedShortcode.name}`

      Object.keys(this.shortcodeParams).forEach(key => {
        const value = this.shortcodeParams[key]
        if (value !== '' && value !== null && value !== undefined) {
          shortcodeStr += ` ${key}="${value}"`
        }
      })

      shortcodeStr += ']'

      if (this.selectedShortcode.hasContent) {
        shortcodeStr += `内容[/${this.selectedShortcode.name}]`
      }

      return shortcodeStr
    },

    insertShortcode() {
      const shortcodeStr = this.generateShortcodeString()
      this.editor.chain().focus().insertContent(shortcodeStr).run()
      this.shortcodeDialogVisible = false
      this.resetShortcodeDialog()
    }
  }
}
</script>

<style scoped>
.insert-menu-wrapper {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 100;
}

.insert-button {
  position: absolute;
  z-index: 999;
  width: 32px;
  height: 32px;
  border: 1px solid #e4e7ed;
  border-radius: 50%;
  background: #ffffff;
  color: #606266;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: all 0.2s ease;
  pointer-events: auto;
}

.insert-button:hover {
  background: #409eff;
  color: #ffffff;
  border-color: #409eff;
  transform: scale(1.1);
}

.insert-icon {
  font-size: 16px;
  font-weight: bold;
}

.insert-menu {
  position: fixed; /* 使用fixed定位,显示在编辑器工具栏下方 */
  left: 50%; /* 水平居中 */
  transform: translateX(-50%); /* 水平居中 */
  z-index: 1000;
  background: #ffffff;
  border: 1px solid #e4e7ed;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
  max-height: 500px;
  overflow-y: auto;
  min-width: 450px;
  pointer-events: auto;
  /* top通过JavaScript动态计算,显示在.ai-toolbar下方 */
}

.menu-section {
  padding: 12px 0;
}

.menu-section + .menu-section {
  border-top: 1px solid #f0f0f0;
}

.section-title {
  font-size: 12px;
  color: #909399;
  font-weight: 600;
  padding: 0 16px 8px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
}

/* 基本组件样式 - 小图标，紧凑布局 */
.basic-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(35px, 1fr));
  gap: 4px;
  padding: 0 16px;
}

.basic-item {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px 4px;
  cursor: pointer;
  transition: all 0.2s ease;
  border-radius: 4px;
  border: 1px solid #e4e7ed;
  background: #fafbfc;
  min-height: 32px;
  aspect-ratio: 1;
}

.basic-item:hover {
  background: #f0f9ff;
  border-color: #409eff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
}

.basic-icon {
  font-size: 14px;
  font-weight: bold;
  color: #606266;
  line-height: 1;
}

.basic-item:hover .basic-icon {
  color: #409eff;
}

/* 默认选中项样式 */
.basic-item.selected-item {
  background: #f0f9ff;
  border-color: #409eff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
}

.basic-item.selected-item .basic-icon {
  color: #409eff;
}

/* 搜索提示样式 */
.search-hint {
  padding: 8px 16px;
  background: #f0f9ff;
  border-bottom: 1px solid #e1f5fe;
  font-size: 12px;
  color: #1976d2;
}

/* 过滤后的网格布局 */
.filtered-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
  gap: 8px;
  padding: 12px 16px;
}

/* 菜单项卡片样式 */
.menu-item-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 12px 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  border-radius: 6px;
  border: 1px solid #e4e7ed;
  background: #fafbfc;
  min-height: 70px;
  position: relative;
}

.menu-item-card:hover {
  background: #f0f9ff;
  border-color: #409eff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
}

.menu-item-card .item-icon {
  font-size: 18px;
  margin-bottom: 6px;
  font-weight: bold;
  color: #606266;
}

.menu-item-card .item-label {
  font-size: 11px;
  color: #606266;
  font-weight: 500;
  text-align: center;
  line-height: 1.2;
  max-width: 100%;
  word-break: break-word;
}

.menu-item-card:hover .item-icon,
.menu-item-card:hover .item-label {
  color: #409eff;
}

/* 默认选中项样式 */
.menu-item-card.selected-item {
  background: #f0f9ff;
  border-color: #409eff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
}

.menu-item-card.selected-item .item-icon,
.menu-item-card.selected-item .item-label {
  color: #409eff;
}

/* 键盘选中状态样式 */
.menu-item-card.keyboard-selected {
  background: #e6f7ff !important;
  border-color: #409eff !important;
  transform: translateY(-1px) !important;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.25) !important;
}

.menu-item-card.keyboard-selected .item-icon,
.menu-item-card.keyboard-selected .item-label {
  color: #409eff !important;
}

/* 搜索高亮样式 */
.menu-item-card .item-label mark {
  background: #fff3cd;
  color: #856404;
  padding: 1px 2px;
  border-radius: 2px;
  font-weight: bold;
}

/* 无结果提示 */
.no-results {
  text-align: center;
  padding: 24px 16px;
  color: #909399;
}

.no-results-text {
  font-size: 14px;
  margin-bottom: 8px;
}

.no-results-hint {
  font-size: 12px;
  color: #c0c4cc;
}

/* 其他组件样式 - 图标+文字，垂直布局 */
.component-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
  gap: 8px;
  padding: 0 16px;
}

.component-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 12px 8px;
  cursor: pointer;
  transition: all 0.2s ease;
  border-radius: 8px;
  border: 1px solid #e4e7ed;
  background: #fafbfc;
  min-height: 80px;
}

.component-item:hover {
  background: #f0f9ff;
  border-color: #409eff;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.15);
}

.component-icon {
  font-size: 24px;
  line-height: 1;
  margin-bottom: 6px;
}

.component-text {
  font-size: 12px;
  color: #606266;
  font-weight: 500;
  text-align: center;
  line-height: 1.2;
}

.component-item:hover .component-text {
  color: #409eff;
}

/* 保留原有的菜单样式以防短代码列表需要 */
.menu-items {
  display: flex;
  flex-direction: column;
}

.menu-item {
  display: flex;
  align-items: center;
  padding: 8px 16px;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.menu-item:hover {
  background-color: #f5f7fa;
}

.item-icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f0f9ff;
  border: 1px solid #e1f5fe;
  border-radius: 6px;
  font-weight: bold;
  font-size: 14px;
  color: #409eff;
  margin-right: 12px;
  flex-shrink: 0;
}

.item-text {
  flex: 1;
}

.item-name {
  font-size: 14px;
  color: #303133;
  font-weight: 500;
  margin-bottom: 2px;
}

.item-desc {
  font-size: 12px;
  color: #909399;
}

/* 对话框样式 */
.shortcode-list {
  max-height: 300px;
  overflow-y: auto;
}

.shortcode-item {
  display: flex;
  align-items: center;
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  margin-bottom: 8px;
  cursor: pointer;
  transition: all 0.2s ease;
}

.shortcode-item:hover {
  border-color: #409eff;
  background-color: #f0f9ff;
}

.shortcode-icon {
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f0f9ff;
  border-radius: 6px;
  font-size: 18px;
  margin-right: 12px;
}

.shortcode-info {
  flex: 1;
}

.shortcode-name {
  font-size: 14px;
  font-weight: 500;
  color: #303133;
  margin-bottom: 4px;
}

.shortcode-desc {
  font-size: 12px;
  color: #909399;
}

.shortcode-config {
  margin-top: 20px;
  padding-top: 20px;
  border-top: 1px solid #f0f0f0;
}

.shortcode-preview {
  margin-top: 12px;
  padding: 8px 12px;
  background: #f5f7fa;
  border-radius: 4px;
  font-size: 12px;
}

.shortcode-preview code {
  color: #e6a23c;
  font-family: 'Monaco', 'Consolas', monospace;
}

/* 动画效果 */
.fade-enter-active, .fade-leave-active {
  transition: all 0.2s ease;
}

.fade-enter, .fade-leave-to {
  opacity: 0;
  transform: scale(0.9);
}

.slide-fade-enter-active {
  transition: all 0.3s ease;
}

.slide-fade-leave-active {
  transition: all 0.2s ease;
}

.slide-fade-enter, .slide-fade-leave-to {
  opacity: 0;
  transform: translateX(-20px);
}
</style>
